--[[
Author: songbb
All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.

对lua原生的扩展

]]

string.trim = string.trim or function(input)
    input = string.gsub(input, "^[ \t\n\r]+", "")
    return string.gsub(input, "[ \t\n\r]+$", "")
end

string.split = string.split or function(input, delimiter)
    input = tostring(input)
    delimiter = tostring(delimiter)
    if (delimiter=='') then return false end
    local pos,arr = 0, {}
    -- for each divider found
    for st,sp in function() return string.find(input, delimiter, pos, true) end do
        table.insert(arr, string.sub(input, pos, st - 1))
        pos = sp + 1
    end
    table.insert(arr, string.sub(input, pos))
    return arr
end

string.startswith = string.startswith or function(str, s_start)
    return type(str) == "string" and type(s_start) == "string" and
            str ~= "" and s_start ~= "" and string.sub(str, 1, string.len(s_start)) == s_start
end

string.endswith = string.endswith or function(str, s_end)
    return type(str) == "string" and type(s_end) == "string" and
            str ~= "" and string.sub(str, -string.len(s_end)) == s_end
end

--[[--

混淆字符串

@param string str 被混淆的字符串
@param string replace 要替换的字符

@return string 混淆后的字符串

@samples
    "a"                 ->   "a"
    "ab"                ->   "a*"
    "abc"               ->   "a*c"
    "abcd"              ->   "a**d"
    "abcde"             ->   "ab**e"
    "abcdef"            ->   "ab**ef"
                        ...
    "abcdefghij"        ->   "ab******ij"
    "abcdefghijk"       ->   "abc****hijk"
    "abcdefghijkl"      ->   "abc******jkl"
                        ...
    "abcdefghijklmno"   ->   "abc*********mno"
    "abcdefghijklmnop"  ->   "abcd********mnop"
                        ...
]]
string.mix = string.mix or function(str, replace)
    assert(type(str) == 'string', debug.traceback())
    if replace ~= nil then
        assert(type(replace) == 'string', debug.traceback())
    else
        replace = "*"
    end

    local i_str_len = string.len(str)

    if i_str_len <= 1 then
        return str
    elseif i_str_len == 2 then
        return string.sub(str, 1, 1) .. replace
    elseif i_str_len == 3 then
        return string.sub(str, 1, 1) .. replace .. string.sub(str, -1)
    elseif i_str_len == 4 then
        return string.sub(str, 1, 1) .. string.rep(replace, 2) .. string.sub(str, -1)
    elseif i_str_len == 5 then
        return string.sub(str, 1, 2) .. string.rep(replace, 2) .. string.sub(str, -1)
    elseif i_str_len >= 6 and i_str_len <= 10 then
        return string.sub(str, 1, 2) .. string.rep(replace, i_str_len - 4) .. string.sub(str, -2, -1)
    elseif i_str_len == 11 then
        return string.sub(str, 1, 3) .. string.rep(replace, 4) .. string.sub(str, -4, -1)
    elseif i_str_len >= 12 and i_str_len <= 15 then
        return string.sub(str, 1, 3) .. string.rep(replace, i_str_len - 6) .. string.sub(str, -3, -1)
    else
        return string.sub(str, 1, 4) .. string.rep(replace, i_str_len - 8) .. string.sub(str, -4, -1)
    end

    return str
end

table.dump = table.dump or function(value, nesting, behavior)
    if type(nesting) ~= "number" then nesting = math.huge end
    if not behavior then behavior = 'print' end

    local lookupTable = {}
    local result = {}

    local function _v(v)
        if type(v) == "string" then
            v = "\"" .. v .. "\""
        end
        return tostring(v)
    end

    if behavior == 'print' then
        local traceback = string.split(debug.traceback("", 2), "\n")
        print("dump from: " .. string.trim(traceback[3]))
    end

    local function _dump(value, desciption, indent, nest, keylen)
        local spc = ""
        if nest > 1 then spc = ',' end
        --[[
        if type(keylen) == "number" then
            spc = string.rep(" ", keylen - string.len(_v(desciption)))
        end
        --]]
        if type(value) ~= "table" then
            if type(desciption) == 'string' then
                if nest <= nesting then
                    result[#result +1] = string.format("%s[\"%s\"] = %s%s", indent, desciption, _v(value), spc)
                elseif nest - nesting == 1 then
                    result[#result+1] = string.format("%s[\"%s\"] = \"*MAX NESTING*\",", indent, desciption)
                end
            else
                if nest <= nesting then
                    result[#result +1] = string.format("%s%s%s", indent, _v(value), spc)
                end
            end
        elseif not lookupTable[value] then
            lookupTable[value] = true

            if type(desciption) == 'string' then
                if nest <= nesting then
                    result[#result+1] = string.format("%s[\"%s\"] = {", indent, desciption)
                else
                    result[#result+1] = string.format("%s[\"%s\"] = \"*MAX NESTING*\",", indent, desciption)
                end
            else
                if nest <= nesting then
                    result[#result+1] = string.format("%s{", indent)
                end
            end
            local indent2 = indent.."    "
            local keys = {}
            local keylen = 0
            local values = {}
            for k, v in pairs(value) do
                keys[#keys + 1] = k
                local vk = _v(k)
                local vkl = string.len(vk)
                if vkl > keylen then keylen = vkl end
                values[k] = v
            end
            table.sort(keys, function(a, b)
                if type(a) == "number" and type(b) == "number" then
                    return a < b
                else
                    return tostring(a) < tostring(b)
                end
            end)
            for i, k in ipairs(keys) do
                _dump(values[k], k, indent2, nest + 1, keylen)
            end
            if nest <= nesting then
                result[#result+1] = string.format("%s}%s", indent, spc)
            end
        end
    end
    _dump(value, nil, "", 1)

    if behavior == 'table' then
        return result
    elseif behavior == 'string' then
        return table.concat(result, '\n')
    elseif behavior == 'print' then
        for i, line in ipairs(result) do
            print(line)
        end
    end
end

--[[
  注意: 最大支持两层table
    mergeTable({1, {2}}, {3, {4}})
    ==>
    {
        1,
        {
            2,
        },
        3,
        {
            4,
        },
    }

    mergeTable({['a'] = 'a', {['b'] = 'b'}}, {['c'] = 'c', {['d'] = 'd'}})
    ==>
    {
        {
            ["b"] = "b",
        },
        {
            ["d"] = "d",
        },
        ["a"] = "a",
        ["c"] = "c",
    }


    合并超过两层table时出现异常,如mergeTable({1, {2, {3}}}, {4, {5, {6}}})
    ==>
    {
        1,
        {
            2,
            {
            },
        },
        4,
        {
            5,
            {
            },
        },
    }
    或者如mergeTable({['a'] = 'a', {['b'] = 'b'}, {['c'] = 'c'}}, {['d'] = 'd', {['e'] = 'e'}})
    ==>
    {
        {
            ["b"] = "b",
        },
        {
            ["c"] = "c",
        },
        {
            ["e"] = "e",
        },
        ["a"] = "a",
        ["d"] = "d",
    }
]]
table.merge = table.merge or function(t1, t2)
    local res = {}
    for k, v in pairs(t1) do
        if type(k) == 'number' then
            table.insert(res, v)
        else
            res[k] = v
        end
    end
    for k, v in pairs(t2) do
        if type(k) == 'number' then
            table.insert(res, v)
        else
            res[k] = v
        end
    end
    return res
end
